#include <stdio.h>
#include <time.h>
#include <gmp.h>
#include "montecarlo.h"

#define IT_N_SIZE 32
#define	N_BITS_RAND 64

void init_randcore(RANDCORE* rc){
	static int i = 0;
	
	i++;
	rc->seed = i + time(NULL);

	gmp_randinit_default (rc->r_state);
    gmp_randseed_ui(rc->r_state, rc->seed);

    mpz_init(rc->iRand);	
	mpf_init(rc->aux1);
	mpf_init(rc->aux2);
	mpf_init(rc->aux3);
	mpf_init(rc->aux4);
	mpf_init(rc->x);
	mpf_init(rc->y);
}

void clear_randcore(RANDCORE* rc){
	gmp_randclear(rc->r_state);
    mpz_clear(rc->iRand);	
	mpf_clear(rc->aux1);
	mpf_clear(rc->aux2);
	mpf_clear(rc->aux3);
	mpf_clear(rc->aux4);
	mpf_clear(rc->x);
	mpf_clear(rc->y);
}

int get_rand_point(RANDCORE* rc){
	int i = 0;

	mpf_set_ui(rc->aux1, 1);
	mpf_set_ui(rc->x, 0);
	mpf_set_ui(rc->y, 0);

	while(i==0){
		mpf_div_2exp(rc->aux1, rc->aux1, N_BITS_RAND);

		mpz_urandomb(rc->iRand, rc->r_state, N_BITS_RAND);

		mpf_set_z(rc->aux2, rc->iRand);
		mpf_mul(rc->aux2, rc->aux2, rc->aux1);
		mpf_add(rc->x, rc->x, rc->aux2);
	
		mpz_urandomb(rc->iRand, rc->r_state, N_BITS_RAND);
		mpf_set_z(rc->aux2, rc->iRand);
		mpf_mul(rc->aux2, rc->aux2, rc->aux1);
		mpf_add(rc->y, rc->y, rc->aux2);

		mpf_pow_ui(rc->aux3, rc->x, 2);
		mpf_pow_ui(rc->aux4, rc->y, 2);
		mpf_add(rc->aux2, rc->aux3, rc->aux4);

		if(0 > mpf_cmp_ui(rc->aux2, 1)){
			mpf_add(rc->aux3, rc->x, rc->aux1);
			mpf_add(rc->aux4, rc->y, rc->aux1);
			mpf_pow_ui(rc->aux3, rc->aux3, 2);
			mpf_pow_ui(rc->aux4, rc->aux4, 2);
			mpf_add(rc->aux2, rc->aux3, rc->aux4);
			if(0 >= mpf_cmp_ui(rc->aux2, 1)) i=1; 
		}
		else {
			i=2;
		}		
	}
	
	if(i==1) return 1;
	else return 0;
}

void init_counters(COUNTERS* c){
	mpf_init(c->in);
	mpf_init(c->all);
	mpf_init(c->pi);
}

void clear_counters(COUNTERS* c){
	mpf_clear(c->in);
	mpf_clear(c->all);
	mpf_clear(c->pi);
}

void add_count(COUNTERS* c, int f){
	mpf_add_ui (c->all, c->all, 1);
	if(f) mpf_add_ui (c->in, c->in, 4);
}

void calc_pi(COUNTERS* c){
	mpf_div (c->pi , c->in, c->all);
}

void save_it(COUNTERS* c, char* name){
	static int it = 0;
	FILE *fd;
	char it_name[IT_N_SIZE];

	sprintf(it_name, "%s-it%d.txt", name, ++it);
    fd = fopen(it_name, "w");
    gmp_fprintf(fd, "%.1000Ff\n", c->pi);
    fclose(fd);
}






